package org.xiaojinlong.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

public class SharedResource implements Runnable {
    private int i = 0;
    public synchronized int getValue() { return i; }
    private synchronized void evenIncrement() { i++; i++; }
    public void run() {
        while (true)
            evenIncrement();
    }
    public static void main(String[] args) {
//        EvenChecker.test(new EvenGenerator());
        ExecutorService exec = Executors.newCachedThreadPool();
        SharedResource sr = new SharedResource();
        exec.execute(sr);
        while (true) {
            int val = sr.getValue();
            if (val % 2 != 0) {
                System.out.println(val);
                System.exit(0);
            }
        }
    }
}

abstract class IntGenerator {
    private volatile boolean canceled = false;
    public abstract int next();
    // Allow this to be canceled
    public void cancel() { canceled = true; }
    public boolean isCanceled() { return canceled; }
}

class EvenGenerator extends IntGenerator {
    private int currentEvenValue = 0;
    public synchronized int next() {
        ++currentEvenValue;
        Thread.yield();
        ++currentEvenValue;
        return currentEvenValue;
    }
}

class AtomicEvenGenerator extends IntGenerator {
    // 使用AtomicInteger消除了synchronized关键字
    private AtomicInteger currentEvenValue =
            new AtomicInteger(0);

    @Override
    public int next() {
        return currentEvenValue.addAndGet(2);
    }
}

class EvenChecker implements Runnable {
    private IntGenerator generator;
    private final int id;
    public EvenChecker(IntGenerator g, int ident) {
        generator = g;
        id = ident;
    }
    @Override public void run() {
        while (!generator.isCanceled()) {
            int val = generator.next();
            if (val % 2 != 0) {
                System.out.println(val + " not even!");
                generator.cancel(); // Cancels all EvenCheckers
            }
        }
    }
    // Test any type of IntGenerator
    public static void test(IntGenerator gp, int count) {
        System.out.println("Press Control-C to exit");
        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < count; i++)
            exec.execute(new EvenChecker(gp, i));
        exec.shutdown();
    }
    // Default value for count
    public static void test(IntGenerator gp) {
        test(gp, 10);
    }
}
